package javabase.ionio.io;

import java.io.Externalizable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

/**
 *  无论是使用transient关键字，还是使用writeObject()和readObject()方法，
 *  其实都是基于Serializable接口的序列化。JDK中提供了另一个序列化接口--Externalizable，
 *  使用该接口之后，之前基于Serializable接口的序列化机制就将失效。
 */
class Person0 implements Externalizable {
	
	private String name;
	
	private transient int age;
	
	//  另外，若使用Externalizable进行序列化，当读取对象时，会调用被序列化类的无参构造器去创建一个新的对象，
	// 然后再将被保存对象的字段的值分别填充到新对象中。这就是为什么在此次序列化过程中Person0类的无参构造器会被调用。
	public Person0() {
        System.out.println("none-arg constructor");
	}
	public Person0(String name, int age) {
		super();
		System.out.println("arg constructor");
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	private void writeObject(ObjectOutputStream out) throws IOException {
	    out.defaultWriteObject();
	    out.writeInt(age);
	}
	
	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
	    in.defaultReadObject();
	    age = in.readInt();
	}
	
	@Override
	public String toString() {
		return "Person0 [name=" + name + ", age=" + age + "]";
	}
	
	/*
	 *  Externalizable继承于Serializable，当使用该接口时，序列化的细节需要由程序员去完成。
	 *  如上所示的代码，由于writeExternal()与readExternal()方法未作任何处理，
	 *  那么该序列化行为将不会保存/读取任何一个字段。这也就是为什么输出结果中所有字段的值均为空。
	 */
	
	public void writeExternal(ObjectOutput out) throws IOException {
		
	}
	
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
		
	}
	
}

public class ExternalizableDemo {

	public static void main(String[] args) {
		File file = new File("person.out0");

        ObjectOutputStream oout = null;
		try {
			oout = new ObjectOutputStream(new FileOutputStream(file));
			Person0 person0 = new Person0("John", 101);
			oout.writeObject(person0);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (oout != null) {
				try {
					oout.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
  
        ObjectInputStream oin = null;
		try {
			oin = new ObjectInputStream(new FileInputStream(file));
			Object newPerson = oin.readObject(); // 没有强制转换到Person类型
			System.out.println(newPerson);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}  catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				oin.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
